/**
 * Copyright 2014 opencxa.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.cxa.cableModemMonitor;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * @author Christopher Armenio
 *
 */
public class Zoom5341 extends CableModem
{
	public Zoom5341()
	{
		this.updateChannelReadings();
	}
	

	@Override
	public void updateChannelReadings()
	{	
		try
		{
			// we'll usually need to post twice...
			Document doc = getConnection().post();
			if( doc.getElementsContainingText("Modem Logout").size() > 0 )
			{
				doc = getConnection().post();
				if( doc.getElementsContainingText("Modem Configuration").size() < 0 )
				{
					throw new RuntimeException("error getting webpage data");
				}
			}
	
			// iterate over all returned elements
			for( Element currTable : doc.getElementsByTag("table") )
			{
				if( isTable_downstream(currTable) ) this.chanReadings_downstream = getChannels_downstream(currTable);			
				else if( isTable_upstream(currTable) ) this.chanReadings_upstream = getChannels_upstream(currTable);
			}
			
			this.dateOfLastReading = new Date();
		}
		catch(IOException e)
		{
			System.err.println("error reading modem data");
			this.dateOfLastReading = null;
			this.chanReadings_upstream = null;
			this.chanReadings_downstream = null;
		}
	}
	

	private static Connection getConnection()
	{
		return Jsoup.connect("http://192.168.100.1/goform/login")
				.referrer("http://192.168.100.1/RGConnect.asp")
				.followRedirects(true)
				.data("name", "login")
				.data("loginUsername", "admin")
				.data("loginPassword", "arb661")
				// and other hidden fields which are being passed in post request.
				.userAgent("Mozilla");
	}
	
	
	private static boolean isTable_downstream(Element currTableIn)
	{
		return (currTableIn.getElementsContainingText("Downstream Bonded Channels").size() != 0);
	}
	
	
	private static boolean isTable_upstream(Element currTableIn)
	{
		return (currTableIn.getElementsContainingText("Upstream Bonded Channels").size() != 0);
	}
	
	
	private static List<DownstreamChannelReading> getChannels_downstream(Element currTableIn)
	{
		List<DownstreamChannelReading> retVal = new ArrayList<DownstreamChannelReading>();
		
		// first child is 'tbody'
		Elements childNodes = currTableIn.children();
		if( childNodes.size() != 1 ) return null;
		Element tbody = childNodes.get(0);
		
		if( tbody.children().size() != 10 ) return null;
		
		for( int i = 0; i < 8; i++ )
		{
			retVal.add(new DownstreamChannelReading(i+1, tbody.child(i+2)));
		}
		
		return retVal;
	}
	
	
	private static List<UpstreamChannelReading> getChannels_upstream(Element currTableIn)
	{
		List<UpstreamChannelReading> retVal = new ArrayList<UpstreamChannelReading>();
		
		// first child is 'tbody'
		Elements childNodes = currTableIn.children();
		if( childNodes.size() != 1 ) return null;
		Element tbody = childNodes.get(0);
		
		if( tbody.children().size() != 6 ) return null;
		
		for( int i = 0; i < 4; i++ )
		{
			retVal.add(new UpstreamChannelReading(i+1, tbody.child(i+2)));
		}
		
		return retVal;
	}
}
